import common from '@ohos.app.ability.common';
import log from '../logutil';
import distributedKVStore from '@ohos.data.distributedKVStore';
import App from '@system.app';
/**
 * 全局单例，用于管理应用内简单的键值对持久化
 */
export default class kvStoreUtil{
  private static instance:null|kvStoreUtil
  private kvManager:distributedKVStore.KVManager;
  private readonly options={
    createIfMissing: true, // 当数据库文件不存在时是否创建数据库，默认创建
    encrypt: false, // 设置数据库文件是否加密，默认不加密
    backup: true, // 设置数据库文件是否备份，默认备份
    kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION, // 设置要创建的数据库类型，默认为多设备协同数据库
    securityLevel: distributedKVStore.SecurityLevel.S2 // 设置数据库安全级别
  }
  private kvStore:distributedKVStore.SingleKVStore
  private readonly storeId = "preference"
  private bundleName:string
  /**
   * 初始化kvStoreUtil
   * @param context
   */
  static async init(context:common.Context){
    if(this.instance!==null && this.instance!==undefined){
      log.warn(kvStoreUtil.name,"kvStoreUtil has been already init.")
      return;
    }
    try{
      let bundleName = await context.resourceManager.getStringValue($r('app.string.bundleName').id)
      this.instance = new kvStoreUtil(context,bundleName)
      log.info(kvStoreUtil.name,"kvManager create success.")
      await this.instance.kvManager.getKVStore<distributedKVStore.SingleKVStore>(this.instance.storeId,this.instance.options).then((store)=>{
        this.instance.kvStore = store;
        log.info(kvStoreUtil.name,"Get KVstore success.")
      }).catch((err)=>{
        log.error(kvStoreUtil.name,`Get KVstore failed. Error:${JSON.stringify(err)}`)
      })
    }catch (e){
      log.error(kvStoreUtil.name,JSON.stringify(e))
      throw e
    }
  }
  /**
   * 获取kvStore
   * @param context
   * @throws Error,当未创建kvStore且未传入context时会发生该错误
   * @returns
   */
  static getInstance(){
    if(this.instance!==null && this.instance !== undefined){
      return this.instance
    }else{
      throw new Error("You need init first.")
      log.error(kvStoreUtil.name,"getInstance has been executed before init.")
    }
  }
  private constructor(context:common.Context,bundleName:string) {
    this.bundleName = bundleName
    this.kvManager = distributedKVStore.createKVManager({
      context:context,
      bundleName: this.bundleName
    })
  }
  public async reloadKVstore(){
    let res = await this.kvManager.getKVStore<distributedKVStore.SingleKVStore>(this.storeId,this.options)
    if(res===undefined){
      this.kvStore = res
      log.info(kvStoreUtil.name,"Reload KVstore success.")
    }else{
      log.error(kvStoreUtil.name,"Reload KVstore failed.")
    }
  }

  public async put(key:string,value:string){
      if(this.kvStore === null || this.kvStore === undefined){
        log.warn(kvStoreUtil.name,`kvStore is ${JSON.stringify(this.kvStore)}, start reload.`)
        await this.reloadKVstore()
      }
      this.kvStore.put(key,value)
      this.kvStore.commit()
  }

  public async get(key:string):Promise<string>{
    if(this.kvStore === null || this.kvStore === undefined){
      log.warn(kvStoreUtil.name,`kvStore is ${JSON.stringify(this.kvStore)}, start reload.`)
      await this.reloadKVstore()
    }
    return await this.kvStore.get(key) as string
  }

  public closed(){
    this.kvManager.closeKVStore(this.bundleName,this.storeId).then(()=>{
      log.info(kvStoreUtil.name,"succeeded in closing kvstore.")
    }).catch(err=>{
      log.warn(kvStoreUtil.name,`failed to close kvstore. Error:${JSON.stringify(err)}`)
    })
  }
}
